package com.heima.wemedia.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.heima.common.constants.WemediaConstants;
import com.heima.common.redis.CacheService;
import com.heima.model.common.dtos.PageResponseResult;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.wemedia.dtos.ChannelDto;
import com.heima.model.wemedia.pojos.WmChannel;
import com.heima.model.wemedia.pojos.WmNews;
import com.heima.wemedia.mapper.WmChannelMapper;
import com.heima.wemedia.service.WmChannelService;
import com.heima.wemedia.service.WmNewsService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;

/**
 * 对频道 增删改 的时候删除redis缓存，
 * 查询时优先查询缓存，没有数据则查询数据库，并将查询到的数据添加到redis
 * （但是 分页查询 如何改为从缓存中查询数据呢？？）
 * */
@Slf4j
@Service
public class WmChannelServiceImpl extends ServiceImpl<WmChannelMapper, WmChannel> implements WmChannelService {
    @Autowired
    private WmNewsService wmNewsService;
    @Autowired
    private CacheService cacheService;


    /*
     * 删除频道
     * */
    @Override
    public ResponseResult delete(Integer id) {
        //参数校验
        if(id == null)
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);

        //业务处理
        //只有禁用的频道才能删除
        WmChannel channel = getById(id);
        if(!channel.getStatus()){//禁用:false
            removeById(id);
        }else {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID,"当前频道无法删除");
        }

        //清空redis缓存中的 频道 数据
        cacheService.delete(WemediaConstants.WM_NEWS_CHANNELS);

        //返回结果
        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }

    /*
     * 频道名称模糊分页查询
     * */
    @Override
    public ResponseResult lists(ChannelDto dto) {
        //1.参数校验
        if(dto == null)
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);

        //2.构建分页构造器
        Page page = new Page(dto.getPage(),dto.getSize());
        LambdaQueryWrapper<WmChannel> name = new LambdaQueryWrapper<>();
        if(StringUtils.isNotBlank(dto.getName())){
             name.like(WmChannel::getName, dto.getName());
        }
        //3.查询数据
        page(page,name);

        //4.封装结果返回
        ResponseResult result = new PageResponseResult(dto.getPage(),dto.getSize(),(int)page.getTotal());
        result.setData(page.getRecords());
        result.setCode(AppHttpCodeEnum.SUCCESS.getCode());
        result.setErrorMessage(AppHttpCodeEnum.SUCCESS.getErrorMessage());
        return result;
    }

    /*
     * 保存频道
     * */
    @Override
    public ResponseResult saves(WmChannel wmChannel) {
        //1.参数校验
        if(wmChannel == null || wmChannel.getName() == null)
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);

        //2.业务处理
        //2.1频道名词不能重复
        WmChannel name = getOne(Wrappers.<WmChannel>lambdaQuery().eq(WmChannel::getName, wmChannel.getName()));
        if(name != null)//不为空说明已存在
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_EXIST);
        //2.2保存到数据库
        wmChannel.setCreatedTime(new Date());
        save(wmChannel);

        //清空redis缓存中的 频道 数据
        cacheService.delete(WemediaConstants.WM_NEWS_CHANNELS);

        //3.返回结果
        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }


    /*
     *修改频道
     * */
    @Override
    public ResponseResult updates(WmChannel wmChannel) {
        //参数校验
        if(wmChannel == null || wmChannel.getId() == null)
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);

        //业务处理
        //如果频道被引用则不能禁用
        int count = wmNewsService.count(Wrappers.<WmNews>lambdaQuery().eq(WmNews::getChannelId, wmChannel.getId())
                .eq(WmNews::getStatus, WmNews.Status.PUBLISHED.getCode()));
        if(count > 0 && !wmChannel.getStatus())
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID,"频道被引用无法禁用");

        updateById(wmChannel);

        //清空redis缓存中的 频道 数据
        cacheService.delete(WemediaConstants.WM_NEWS_CHANNELS);

        //返回结果
        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }

    /**
     * 频道列表查询（缓存）
     */
    @Override
    public ResponseResult channels() {
        //优先从缓存中读取数据
        String data = cacheService.get(WemediaConstants.WM_NEWS_CHANNELS);
        if(StringUtils.isNotBlank(data)){
            List<WmChannel> wmChannel = JSON.parseObject(data, List.class);
            return ResponseResult.okResult(wmChannel);
        }else {
            //没有数据则从数据库读取
            List<WmChannel> channelList = list();
            //将读取到的数据保存到redis缓存
            cacheService.set(WemediaConstants.WM_NEWS_CHANNELS,JSON.toJSONString(channelList));

            return ResponseResult.okResult(channelList);
        }
    }


}
